<script setup lang="ts">
import { createProgressHandler, createFileChunk, sha256Hash } from '@/views/file/utils'
import Request from '@/api/xhr'
import ChunkUpload from './ChunkUpload.vue'
import { computed, ref, watch } from 'vue'
import Chance from 'chance'
const chance = new Chance()
const { file, upload, chunkSize } = defineProps(['file', 'upload', 'chunkSize'])
const emit = defineEmits(['uploadok'])
const uploadchunkList = ref<any[]>([])
const uploadPercentage = computed(() => {
    if (upload === false) return 0
    if (uploadchunkList.value.length === 0) return 0
    const loadedSize = uploadchunkList.value
        .map((item) => item.chunk.size * item.percentage)
        .reduce((acc, cur) => acc + cur)
    return parseInt((loadedSize / file.size).toFixed(2))
})

watch(
    () => upload,
    async () => {
        if (!upload) return
        const chunkList = createFileChunk(file, chunkSize * 1024 * 1024) // 1MB
        uploadchunkList.value = await Promise.all(chunkList.map(async (chunk, index) => ({
            chunk,
            index,
            hash: sha256Hash(
                `${file.name}${chance.string({ length: 6 })}${index}${Date.now().toString(16).slice(4)}`
            ),
            percentage: 0
        })))
        await uploadChunks(uploadchunkList.value, file.name).then(() => {
            emit('uploadok')
        })
    }
)

const uploadChunks = async (data: any[], filename: string) => {
    const requestList = data
        .map(({ chunk, hash, index }) => {
            const formData = new FormData()
            formData.append('chunk', chunk)
            formData.append('hash', hash)
            formData.append('index', index)
            return { formData, index }
        })
        .map(({ formData, index }) => {
            return Request({
                url: '/api/file/upload',
                data: formData,
                onProgress: createProgressHandler(data[index])
            })
        })
    const results = await Promise.allSettled(requestList)
    const failedRequests = results.filter((result) => result.status === 'rejected')
    if (failedRequests.length > 0) {
        throw new Error(`部分文件块上传失败: ${failedRequests.length} 个`)
    }
    ; (async () => {
        const formData = new FormData()
        formData.append('filename', filename)
        formData.append('hashList', data.map(({ hash }) => hash) as any)
        return Request({
            url: '/api/upload/merge',
            data: formData
        })
    })()
}
</script>

<template>
    <a-progress :percent="uploadPercentage" />
    <!-- <div v-for="(item, index) in uploadchunkList" :key="index">
        <ChunkUpload :size="item.chunk.size" :index="item.index" :hash="item.hash" :percentage="item.percentage" />
    </div> -->
</template>
